/*This source code copyrighted by Lazy Foo' Productions (2004-2013)
and may not be redistributed without written permission.*/

//Using SDL, standard IO, and strings
#include <SDL.h>
#include <stdio.h>
#include <string>
#include <iostream>
#include <fstream>
#include <../model/ConstructorTerreno.h>
#include <../model/Terreno.h>
#include <../model/Agua.h>
#include <../view/VistaAgua.h>
#include <../controller/ControladorAgua.h>

using namespace std;

//Screen dimension constants
const int SCREEN_WIDTH = 1024;
const int SCREEN_HEIGHT = 768;

//Starts up SDL and creates window
bool init();

//Loads media
bool loadMedia();

//Frees media and shuts down SDL
void close();

//Loads individual image
SDL_Surface* loadSurface( std::string path );

//The window we'll be rendering to
SDL_Window* gWindow = NULL;
	
//The surface contained by the window
SDL_Surface* gScreenSurface = NULL;

//Current displayed image
SDL_Surface* gStretchedSurface = NULL;

SDL_Renderer* gRenderer = NULL;

bool init()
{
	//Initialization flag
	bool success = true;

	//Initialize SDL
	if( SDL_Init( SDL_INIT_VIDEO ) < 0 )
	{
		printf( "SDL could not initialize! SDL Error: %s\n", SDL_GetError() );
		success = false;
	}
	else
	{
		//Create window
		gWindow = SDL_CreateWindow( "Estirando la mascara", SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED, SCREEN_WIDTH, SCREEN_HEIGHT, SDL_WINDOW_SHOWN );
		if( gWindow == NULL )
		{
			printf( "Window could not be created! SDL Error: %s\n", SDL_GetError() );
			success = false;
		}
		else
		{
			//Get window surface
			gScreenSurface = SDL_GetWindowSurface( gWindow );
		}
	}

	return success;
}

bool loadMedia()
{
	//Loading success flag
	bool success = true;

	//Load stretching surface
	gStretchedSurface = loadSurface( "tests/images/stretch.bmp" );
	if( gStretchedSurface == NULL )
	{
		printf( "Failed to load stretching image!\n" );
		success = false;
	}

	return success;
}

void close()
{
	//Free loaded image
	SDL_FreeSurface( gStretchedSurface );
	gStretchedSurface = NULL;

	//Destroy window
	SDL_DestroyWindow( gWindow );
	gWindow = NULL;

	//Quit SDL subsystems
	SDL_Quit();
}

SDL_Surface* loadSurface(string path)
{

	ofstream fp;
	fp.open("loadError.txt");

	
	//The final optimized image
	SDL_Surface* optimizedSurface = NULL;

	//Load image at specified path
	SDL_Surface* loadedSurface = SDL_LoadBMP( path.c_str() );
	if( loadedSurface == NULL )
	{
		fp << "Unable to load image " << path.c_str() << " SDL Error: " << SDL_GetError() << endl;
	}
	else
	{
		//Convert surface to screen format
		optimizedSurface = SDL_ConvertSurface( loadedSurface, gScreenSurface->format, NULL );
		if( optimizedSurface == NULL )
		{
			fp << "Unable to optimize img " << path.c_str() << " SDL Error: " << SDL_GetError() << endl;
		}

		//Get rid of old loaded surface
		SDL_FreeSurface( loadedSurface );
	}
	fp.close();
	return optimizedSurface;
}

/*Uint32 getPixelUint32(SDL_Surface* superficie, int x, int y) 
{
	if(SDL_MUSTLOCK(superficie)) {
		SDL_LockSurface(superficie);
	}
	Uint32 *pixels = (Uint32*)superficie->pixels;
    if(SDL_MUSTLOCK(superficie)) {
		SDL_UnlockSurface(superficie);
	}
	return pixels[(y*superficie->w) + x];
}*/

/*void calcularAlturaTerreno(int* alturas, int ancho, int alto)
	//TODO: cambiar la surface de manera que se adapte al objeto y no a una variable global horrible
{
	Uint8 rojo;
	Uint8 verde;
	Uint8 azul;
	Uint32 pixel;
	for (int x = 0; x < ancho; x++) {
		int y = 0;
		bool bordeEncontrado = false;
		while (!bordeEncontrado && y < alto) {
			pixel = getPixelUint32(gScreenSurface, x, y);
			SDL_GetRGB(pixel, gScreenSurface->format, &rojo, &verde, &azul);
			if (rojo != 255 && verde != 255 && azul != 255) {
				bordeEncontrado = true;
			}
			y++;
		}
		alturas[x] = y;
	}
}*/

/*void dibujarTerreno(int* alturas) {
	SDL_SetRenderDrawColor( gRenderer, 103, 64, 58, 255 );
	for(int x = 0; x < SCREEN_WIDTH; x++) {
		SDL_RenderDrawLine(gRenderer, x, alturas[x], x, SCREEN_HEIGHT -1);
	}
}*/


int main( int argc, char* args[] )
{
	if(!init()) {
		return 1;
	}

	if(!loadMedia()){
		return 2;
	} 

	// Cargar mascara escalada
	// Es muy importante cargar la mascara con BlitScaled para ajustar el tamanio de la misma al de la SDL_Window
	SDL_Rect stretchRect;
	stretchRect.x = 0;
	stretchRect.y = 0;
	stretchRect.w = SCREEN_WIDTH;
	stretchRect.h = SCREEN_HEIGHT;
	SDL_BlitScaled(gStretchedSurface, NULL, gScreenSurface, &stretchRect);
	
	// Iniciar construccion de terreno
	ConstructorTerreno consTerreno(gWindow, 1.0f);
	bool valid = consTerreno.validarMascara();
	if(valid) {
		consTerreno.calcularAlturas();
	} else {
		return 3;
	}

	// renderizo el terreno
	gRenderer = SDL_CreateRenderer(gWindow, -1, SDL_RENDERER_ACCELERATED);
	if( gRenderer == NULL ) {
		printf( "Renderer could not be created! SDL Error: %s\n", SDL_GetError() );
		return 4;
    }

	Agua agua;
	VistaAgua vistaAgua(gRenderer, SCREEN_WIDTH, SCREEN_HEIGHT);
	ControladorAgua controlAgua(&agua, &vistaAgua);
	controlAgua.actualizarVista();
	SDL_RenderPresent(gRenderer);

	
	VistaTerreno vTerreno(gRenderer, SCREEN_WIDTH, SCREEN_HEIGHT);
	vTerreno.dibujar(consTerreno.getAlturasPixel());
	SDL_RenderPresent(gRenderer);

	// Construyo el terreno
	b2Vec2 gravedad(0.0f, -10.0f);
	b2World mundo(gravedad);
	Terreno terreno(consTerreno.getAlturasLogica(), 1.0f, SCREEN_WIDTH, mundo);
	
	//Gameloop
	bool quit = false;
	SDL_Event evento;
	while (!quit) {
		while( SDL_PollEvent( &evento ) != 0 ) {
			if( evento.type == SDL_QUIT ) {
				quit = true;
			}
		}
	}
	close();

	return 0;
}
